package com.sh.gateway.common;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.util.JSONPObject;
import net.sf.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author he changjie
 */
public class JsonMapper {

    public static final JsonMapper INSTANCE = new JsonMapper();
    private static Logger logger = LoggerFactory.getLogger(JsonMapper.class);
    private ObjectMapper mapper;


    //Include.Include.ALWAYS 默认
    //Include.NON_DEFAULT 属性为默认值不序列化
    //Include.NON_EMPTY 属性为空（""） 或者为 NULL 都不序列化
    //Include.NON_NULL 属性为NULL 不序列化
    public JsonMapper() {
        this(null);
    }

    public JsonMapper(JsonInclude.Include include) {
        mapper = new ObjectMapper();
        if (include != null) {
            mapper.setSerializationInclusion(include);
        }
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    }

    /**
     * 将JsonArr转为List<String>
     * @param str
     * @return
     */
    public List<String> toArray(String str){
        if(!str.contains("\"=\"")){
            str=toJsonStr(str);
        }
        JSONArray jsonArray=JSONArray.fromObject(str);
        List<String> list=new ArrayList<>();
        for (Object o : jsonArray.toArray()) {
            list.add(String.valueOf(o));
        }
        return list;
    }

    /**
     * 将原始数据的Json数组字符串转化为标准格式（即key-value都带有"号）
     * 例如：
     *      原始数据："[{type=1, keyword=法轮, level=2}, {type=1, keyword=法 轮 功, level=2}, {type=1, keyword=法轮功, level=2}]";
     *      转化后：[{"type"="1","keyword"="法轮","level"="2"},{"type"="1","keyword"="法轮功","level"="2"},{"type"="1","keyword"="法轮功","level"="2"}]
     * @param dStr 原始数据的Json数组字符串
     * @return 标准格式
     */
    public String toJsonStr(String dStr){
        return dStr.replaceAll(" ", "")
                .replaceAll("}", "\"}")
                .replaceAll("\\{", "{\"")
                .replaceAll(",", "\",\"")
                .replaceAll("=", "\"=\"")
                .replaceAll("}\",\"\\{" , "},{");
    }

    /**
     * 创建只输出非Null属性到Json字符串的mapper
     */
    public static JsonMapper nonNullMapper() {
        return new JsonMapper(JsonInclude.Include.NON_NULL);
    }

    /**
     * 创建只输出非Null且非Empty得属性到Json字符串的mapper
     */
    public static JsonMapper nonEmptyMapper() {
        return new JsonMapper(JsonInclude.Include.NON_EMPTY);
    }

    /**
     * 默认的全部输出mapper，区别于INSTANCE, 可做进一步的配置
     */
    public static JsonMapper defaultMapper() {
        return new JsonMapper();
    }

    /**
     * Object可以是POJO，Collection,数组,  如果对象为Null, 返回"null", 如果集合为空集合，返回[]
     */
    public String toJson(Object object) {
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            logger.warn("Write to json string error:" + object, e);
            return null;
        }
    }

    /**
     * 反序列化POJO或简单Collection如List<String>
     * 如果JSON字符串为Null或“null”，返回Null, 如何JSON字符串为"[]"，返回空集合
     * 如果反序列化复杂Collection如List<Mybean>, 请使用fromJson(String, JavaType)
     */
    public <T> T fromJson(String jsonString, Class<T> clazz) {
        if (StringUtils.isEmpty(jsonString)) {
            return null;
        }
        try {
            return mapper.readValue(jsonString, clazz);
        } catch (IOException e) {
            logger.warn("parse json string error:" + jsonString, e);
            return null;
        }
    }

    /**
     * 反序列化复杂Collection如List<Mybean>,
     * contructCollectionType()或contructMapType()构造类型，然后调用本函数
     */
    public <T> T fromJson(String jsonString, JavaType javaType) {
        if (StringUtils.isEmpty(jsonString)) {
            return null;
        }
        try {
            return (T) mapper.readValue(jsonString, javaType);
        } catch (IOException e) {
            logger.warn("parse json string error:" + jsonString, e);
            return null;
        }
    }

    /**
     * 构造Collection类型
     */
    public JavaType buildCollectionType(Class<? extends Collection> collectionClass, Class<?> elementClass) {
        return mapper.getTypeFactory().constructCollectionType(collectionClass, elementClass);
    }

    /**
     * 构造Map类型
     */
    public JavaType buildMapType(Class<? extends Map> mapClass, Class<?> keyClass, Class<?> valueClass) {
        return mapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass);
    }

    /**
     * 输出JSONP格式数据
     */
    public String toJsonP(String funcionName, Object object) {
        return toJson(new JSONPObject(funcionName, object));
    }

    /**
     * 设定是否使用Enum的toString函数来读写Enum， 为False时使用Enum的name()函数来读写enum，默认为False，本函数
     * 一定要在Mapper创建后
     */
    public void enableEnumUseToString() {
        mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
        mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
    }

    /**
     * 取出Mapper做进一步的设置或使用其他序列化API
     */
    public ObjectMapper getMapper() {
        return mapper;
    }

}
